package com.luyou.a02;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.Objects;


/**
 * BeanFactory的实现
 * 目前可以知道，BeanFactory 不会 ：
 * 主动调用 BeanFactory 后置处理器 ==>初始化类上的bean对象
 * 主动添加 Bean 后置处理器==>初始化bean对象内的bean对象属性
 * 主动初始化单例对象；
 * 解析 ${} 和 #{}
 *
 * BeanFactory 其实就是 Spring Ioc 容器，它本身是一个接口，提供了一系列获取 Bean 的方式。
 * 基于它也有众多子接口：
 * ListableBeanFactory：提供获取 Bean 集合的能力，比如一个接口可能有多个实现，通过该接口下的方法就能获取某种类型的所有 Bean；
 * HierarchicalBeanFactory：Hierarchical 意为 “层次化”，通常表示一种具有层级结构的概念或组织方式，这种层次化结构可以通过父子关系来表示对象之间的关联，比如树、图、文件系统、组织架构等。根据该接口下的方法可知，能够获取到父容器，说明 BeanFactory 有父子容器概念；
 * AutowireCapableBeanFactory：提供了创建 Bean、自动装配 Bean、属性填充、Bean 初始化、依赖注入等能力，比如 @Autowired 注解的底层实现就依赖于该接口的 resolveDependency() 方法；
 * ConfigurableBeanFactory：该接口并未直接继承至 BeanFactory，而是继承了 HierarchicalBeanFactory。Configurable 意为 “可配置的”，就是说该接口用于对 BeanFactory 进行一些配置，比如设置类型转换器。
 *
 */
public class TestBeanFactory  {

    public static void main(String[] args) {
        /**
         * ConfigurationListableBeanFactory和BeanDefinitionRegistry接口的默认实现
         */
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // bean 的定义（class，scope，初始化，销毁）
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class)
                .setScope("singleton")
                .getBeanDefinition();
        //注册config bean
        beanFactory.registerBeanDefinition("config", beanDefinition);
        //此时bean只有手工注册的config 并没有解析@Configuration 和内部的@Bean 注解
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        // 给 BeanFactory 添加一些常用的后置处理器, 仅仅只是注入了后置处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
        System.out.println("添加常用后置处理器--->");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        //获取bean厂后置处理器，并执行后置处理器，此时@Configuration和@Bean被解析
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(i -> i.postProcessBeanFactory(beanFactory));
        System.out.println("执行bean工厂后置处理器--->");
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }

        //此时 @Autowired 和@Resource注解并未解析. 如果没有执行bean的后置处理器。先获取bean。再执行bean后置处理器，后置处理器无效。
//        System.out.println("是否获取到bean1中的bean2 ==>" + beanFactory.getBean(Bean1.class).getBean2());

        /**
         * 处理bean内部的@Autowired和@Resource注解
         *  注入如下bean后置处理
         * internalAutowiredAnnotationProcessor 解析@Autowired
         * internalCommonAnnotationProcessor 解析@Resource
         */
        System.out.println("执行bean后置处理器--->");
//        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanFactory::addBeanPostProcessor);
        // AnnotationConfigUtils.registerAnnotationConfigProcessors 注册顺序打印
//        beanFactory.getBeansOfType(BeanPostProcessor.class).values().forEach(beanPostProcessor -> {
//            System.out.println(">>>> " + beanPostProcessor);
//            beanFactory.addBeanPostProcessor(beanPostProcessor);
//        });
        //使用比较器排序。 internalCommonAnnotationProcessor 》 internalAutowiredAnnotationProcessor
        beanFactory.getBeansOfType(BeanPostProcessor.class).values().stream()
        .sorted(Objects.requireNonNull(beanFactory.getDependencyComparator()))
        .forEach(beanPostProcessor -> {
            System.out.println(">>>> " + beanPostProcessor);
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });
        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        System.out.println("是否获取到bean1中的bean2 ==>" + beanFactory.getBean(Bean1.class).getBean2());

        /**
         * bean注入顺序
         * @Autowired比@Resource先生效
         */
        System.out.println("bean1的getInter获取到的方法 ==>" + beanFactory.getBean(Bean1.class).getInter());

    }


    @Configuration
    static class Config {
        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }

        @Bean
        public Bean3 bean3() {
            return new Bean3();
        }

        @Bean
        public Bean4 bean4() {
            return new Bean4();
        }

    }

    interface Inter{

    }

    static class Bean3 implements Inter{
        public Bean3(){
            System.out.println("构造bean3()");
        }
    }

    static class Bean4 implements Inter{
        public Bean4(){
            System.out.println("构造bean4()");
        }
    }

    static class Bean1 {
        public Bean1() {
            System.out.println("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        /**
         * 看bean的后置处理器的执行顺序，确定生效顺序。
         */
        @Autowired
        @Resource(name = "bean4")
        private Inter bean3;

        public Bean2 getBean2() {
            return bean2;
        }

        private Inter getInter(){
            return bean3;
        }
    }

    static class Bean2 {
        public Bean2() {
            System.out.println("构造 Bean2()");
        }
    }
}



